パフォーマンスチューニング
==================

ウェブアプリケーションのパフォーマンスはさまざまな要因に影響されます。
データベースへのアクセス、ファイルシステム操作、ネットワークの帯域などはすべて潜在的影響要因です。
Yii はフレームワークによって生じるパフォーマンスへの影響をあらゆる側面に渡って少なくするよう努力していますが、そでもユーザアプリケーションにおいてはパフォーマンスを改善するさまざまな場所があります。

APC 拡張を有効にする
----------------------


[PHP APC 拡張](http://www.php.net/manual/ja/book.apc.php) を有効にすることは、アプリケーションのパフォーマンスを改善する最も容易な手段でしょう。
APC は PHP の中間コードを最適化し、キャッシュすることで、リクエストごとに PHP スクリプトが解析されるのを避けます。

デバッグモードを無効にする
--------------------

デバッグモードを無効にすることも、パフォーマンスを改善するもうひとつの簡単な方法です。
Yii アプリケーションは `YII_DEBUG` 定数が true に設定されていると、デバッグモードで動きます。
しかし、デバッグモードではいくつかのコンポーネントが余分な作業を発生させるので、パフォーマンスが低下します。
たとえば、メッセージロガーはあらゆるメッセージが記録される際に、追加のデバッグ情報も記録します。


`yiilite.php`を使う
-------------------

[PHP APC 拡張](http://www.php.net/manual/ja/book.apc.php) が有効である場合、`yii.php`を `yiilite.php` で置き換えることで、さらにパフォーマンスを改善できます。

`yiilite.php` はすべての Yii リリースに含まれています。
その内容は Yii の基本クラスをひとつにまとめたものです。
コメントとトレース命令はすべて取り除かれています。
したがって、`yiilite.php` を使うことで、インクルードされるファイルの数と、トレース命令の実行を減らすことになります。

APC 無しで `yiilite.php` を使うことはパフォーマンスを低下させる可能性があることに注意してください。
`yiilite.php` には必ずしもすべてのリクエストで必要ではないクラスが含まれており、追加の解析時間がかかります。
また、たとえ APC が有効であっても、サーバの設定によっては `yiilite.php` を使うとパフォーマンスが低下することがあります。
`yiilite.php` を使うかどうか決める最良の方法は、Yii フレームワークに同梱の `hello world` デモを使ってベンチマークをすることです。

キャッシュ機構を利用する
------------------------

[キャッシュ概要](/doc/guide/caching.overview) の章で解説したように、Yii はいくつかのキャッシュソリューションを備えており、それらを利用することで、ウェブアプリケーションのパフォーマンスを大幅に改善できる可能性があります。
あるデータの生成に長い時間がかかっているなら、[データキャッシュ](/doc/guide/caching.data) を使ってデータ生成回数を減らすことができます。
ページの一部があまり変更されないなら、[フラグメントキャッシュ](/doc/guide/caching.fragment) を使って描画される回数を減らすことができます。
ページ全体があまり変更されないなら、[ページキャッシュ](/doc/guide/caching.page) を使ってページ描画コストを軽減できます。

アプリケーションで [アクティブレコード](/doc/guide/database.ar) を使っているなら、スキーマキャッシュを有効にして、データベーススキーマの解析時間を減らすべきです。
これは、[CDbConnection::schemaCachingDuration] プロパティを 0 以上の値にすることで可能です。

これらアプリケーションレベルのキャッシュテクニックとは別に、サーバレベルでのキャッシュソリューションを使ってアプリケーションのパフォーマンスを増加させることも可能です。
実のところ、先ほど述べた [APC 拡張を有効にする](/doc/guide/topics.performance#sec-2) はこのカテゴリに含まれます。
ほかにも2,3の例を挙げると、[Zend Optimizer](http://www.zend.com/en/products/guard/zend-optimizer), [eAccelerator](http://eaccelerator.net/), [Squid](http://www.squid-cache.org/) といったものがあります。

データベースの最適化
---------------------

データベースアクセスはウェブアプリケーションにおいてしばしば主なパフォーマンスボトルネックになります。
キャッシュを利用することで、パフォーマンスの頭打ちを軽減することはできるでしょうが、根本的な解決ではありません。
データベースとクエリを適切にデザインしないと、データベースに膨大なデータがあって、しかもキャッシュの有効期限が切れている場合、最新のデータを取得するのは法外なコストがかかります。

データベースのインデックスをかしこく作成しましょう。
インデックスを使えば、`SELECT` クエリはより速くなります。
ただし `INSERT`, `UPDATE`, `DELETE` クエリは遅くなるでしょう。

複雑なクエリには、PHP コードでクエリを発行して DBMS に解析を任せるより、データベースビューを作ることをすすめます。

[アクティブレコード](/doc/guide/database.ar) を使いすぎないでください。
[アクティブレコード](/doc/guide/database.ar) は OOP 流にデータをモデリングするには便利ですが、クエリ結果に対して一つまたは複数のオブジェクトを作る必要があるため、パフォーマンスを低下させます。
膨大なデータを扱うアプリケーションには、[DAO](/doc/guide/database.dao) を使うか、直接データベース API を使うのが賢明な選択でしょう。

言い忘れましたが、`SELECT` クエリで `LIMIT` を使ってください。
こうすることで、大量のデータが返されて、メモリを使い尽くすということがなくなります。

スクリプトファイルを最小化する
-----------------------

複雑なページでは、たくさんの外部 JavaScript ファイルや CSS ファイルを読み込む必要があります。
各ファイルを読み込むごとにサーバとの通信が発生するので、ファイルはなるべくまとめて少なくするべきです。
ファイルのサイズ自体を減らして、通信時間を減らすことも考えるべきでしょう。
このような作業を助けてくれるツールはたくさんあります。

Yii でページを表示する場合、コンポーネントが出力するファイルは変更したくない場合があるでしょう (例: コアコンポーネントやサードパーティコンポーネントなど)。
このようなファイルを最小化するため、二つのステップを踏む必要があります。

まず、[clientScript|CWebApplication::clientScript] コンポーネントの、[scriptMap|CClientScript::scriptMap] プロパティを設定することで、最小化するファイルを設定します。
これは PHP コードの中でも設定できます。
例：
~~~
[php]
$cs=Yii::app()->clientScript;
$cs->scriptMap=array(
	'jquery.js'=>'/js/all.js',
	'jquery.ajaxqueue.js'=>'/js/all.js',
	'jquery.metadata.js'=>'/js/all.js',
	......
);
~~~

上記のコードが実行されると、これらの JavaScript ファイルは、`/js/all.js` という URL に割り当てられます。
これらの JavaScript ファイルのいずれかが必要になった場合、Yii は個別のファイルを読み込むのではなく、URL を一度だけ読み込みます。

次に、JavaScript ファイルをひとつのファイルにまとめる (そしておそらく圧縮する) ツールを使って、`js/all.js` というファイルを作ります。

CSS ファイルも同じようにします。

さらに、[Google AJAX Libraries API](http://code.google.com/apis/ajaxlibs/) を使って、ページのロード時間を改善することができます。
自分のサーバからではなく、Google のサーバから `jquery.js` を読み込むことができます。
そのために、まず `scriptMap` を以下のように設定します。

~~~
[php]
$cs=Yii::app()->clientScript;
$cs->scriptMap=array(
	'jquery.js'=>false,
	'jquery.ajaxqueue.js'=>false,
	'jquery.metadata.js'=>false,
	......
);
~~~

こうすることで、Yii が個別のファイルを読み込むのを防ぎます。
代わりに以下のコードを明示的にページに記述します。

~~~
[php]
<head>
<?php echo CGoogleApi::init(); ?>

<?php echo CHtml::script(
	CGoogleApi::load('jquery','1.3.2') . "\n" .
	CGoogleApi::load('jquery.ajaxqueue.js') . "\n" .
	CGoogleApi::load('jquery.metadata.js')
); ?>
......
</head>
~~~

アセットをシンボリックリンクする
--------------------------------

プロジェクトが多数のアセットファイルを使用する場合は、ファイルコピーの代りに
[シンボリックリンク](http://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%B3%E3%83%9C%E3%83%AA%E3%83%83%E3%82%AF%E3%83%AA%E3%83%B3%E3%82%AF) を使うことでパフォーマンスをわずかに向上させることが出来ます。
アセットのシンボリックリンクを有効にするためには、`protected/config/main.php` 設定ファイルを使用して、
`assetManager` アプリケーション・コンポーネントの [linkAssets|CAssetManager::linkAssets] プロパティを
設定しなければなりません。

~~~
[php]
return array(
	// ...
	'components' => array(
		// ...
		'assetManager' => array(
			'linkAssets' => true,
		),
	),
);
~~~

ただし、[これ以外にも変更しなければならない設定があるかも知れない|CAssetManager::linkAssets] ということに注意して下さい。